﻿using UnityEngine;
using System.Collections.Generic;
using System.Linq;

namespace ZXthex
{
    sealed class FillHoleHelper_Impl0 : FillHoleHelper
    {
        /// <summary>
        /// 不增加新的顶点， 使用已有顶点组成面
        /// </summary>
        public FillHoleHelper_Impl0() { }

        public override Mesh[] GetMeshes(bool needUV = false)
        {

            if (points.Count > 2)
            {
                Mesh mesh1 = new Mesh(), mesh2 = new Mesh();

                List<Vector2> uv = null;
                if (needUV)
                {
                    uv = new List<Vector2>(points.Count);
                }


                List<int> tris = new List<int>();

                var v0 = points[0];
                var mag = (points[1] - v0).sqrMagnitude;
                var maxInd = 1;
                for (int j = 2; j < points.Count; j++)
                {
                    float temp;
                    if ((temp = (points[j] - v0).sqrMagnitude) > mag)
                    {
                        mag = temp;
                        maxInd = j;
                    }
                }
                var dir = (points[maxInd] - v0);
                dir.Normalize();
                points.Sort(1, points.Count - 1,
                    Comparer<Vector3>.Create((x, y) =>
                    {
                        if (x == v0)
                            return -1;
                        if (y == v0)
                            return 1;

                        var dx = (x - v0);
                        var dy = (y - v0);
                        if (dx.normalized != dy.normalized)
                        {

                            return
                            (int)Mathf.Sign(
                                Vector3.SignedAngle(dir, dx.normalized, normal)
                                -
                                Vector3.SignedAngle(dir, dy.normalized, normal)
                                );
                        }

                        return (int)Mathf.Sign(
                            Vector3.Dot(Vector3.Cross(dir, dx), normal)
                            -
                            Vector3.Dot(Vector3.Cross(dir, dy), normal)
                            );

                    })
                );

                for (int i = 2; i < points.Count; i++)
                {
                    tris.Add(0);
                    tris.Add(i);
                    tris.Add(i - 1);

                }

                mesh1.vertices =
                    mesh2.vertices = points.ToArray();

                if (needUV)
                {
                    Quaternion to2D = Quaternion.FromToRotation(normal, Vector3.forward);
                    float maxU = float.MinValue, maxV = float.MinValue, minU = float.MaxValue, minV = float.MaxValue;
                    for (int i = 0; i < points.Count; i++)
                    {
                        Vector2 map = to2D * points[i];
                        if (map.x < minU) minU = map.x;
                        if (map.y < minV) minV = map.y;
                        if (map.x > maxU) maxU = map.x;
                        if (map.y > maxV) maxV = map.y;
                    }
                    float sizeU = maxU - minU;
                    float sizeV = maxV - minV;
                    for (int i = 0; i < points.Count; i++)
                    {
                        Vector2 map = to2D * points[i];
                        uv.Add(new Vector2((map.x - minU) / sizeU, (map.y - minV) / sizeV));
                    }
                    mesh1.uv =
                        mesh2.uv = uv.ToArray();
                }

                mesh1.normals = Enumerable.Repeat(-normal, points.Count).ToArray();
                mesh2.normals = Enumerable.Repeat(normal, points.Count).ToArray();

                mesh1.triangles = tris.ToArray();
                tris.Reverse();

                mesh2.triangles = tris.ToArray();


                return new Mesh[] { mesh1, mesh2 };

            }

            Debug.LogError("无法填补空洞，因为没有空洞！");
            return null;
        }
    }
}